//: Playground - noun: a place where people can play
// 个人练习
import UIKit

//打印

let age = "15"

let name = "小孩"
//字符串 拼接 1
let sum = age + "is" + name

print(sum)


//字符串 拼接 2
let sentence = "\(name) is \(age)"

print(sentence)

//类型转换
let age1 = 15
let name1 = "小孩"
//String 的初始化方法  传入一个 Int 类型的值作为参数值
//let stringAge = String(age1)
//可以在拼接中调用方法
let  sentence1 = "\(name1) is \(String(age1))"

print(sentence1)

//声明可选类型
/**
 *  Swift 中声明一个可选类型可以不赋值，编译也会通过 但是如果我们声明这些变量时不加上可选类型的符号，那么就会报错。 同样，非可选类型在声明的时候也不能被赋值为 nil
 *
 */

var favoriteColor : String?

//var favoriteColor : String

//对于可选类型来说 不对他赋值 他的值为nil
favoriteColor = "Bule"

//对于 不可选类型  他也是不能直接 == nil的
//favoriteColor = nil

print(favoriteColor)



//解包
var favoriteAnimal : String?
var favoriteSong : String?

favoriteAnimal = "Fox"


if let unwrappedFavoriteAnimal = favoriteAnimal {// 如果有值
    print("Favorite animal is:" + unwrappedFavoriteAnimal)
}

if let unwfavoriteSong = favoriteSong{ //如果没有值 则会触发else语句
    print("Favorite Song is :" + unwfavoriteSong)
}else{ //如果没有else 则什么都不会触发
    print("I down know what is your favorite song")
}

//  Swift 提供一种简便方式来一次解包多个变量  都满足的时候 会调用if
if let unwrappedFavoriteAnimal = favoriteAnimal,let unwfavoriteSong = favoriteSong{
    print("全部不为空")
}else{
    print("有一个为空")
}


/**
        集合类
*/


// 数组
// 定义了一个基本的Array 类型  他是字符串数组类型 [String] 这个方括号暗示了它是一个存放字符串对象的数组，而不是一个字符串类型
let starks: [String] = ["Eddard", "Catelyn", "Robb", "Sansa"]
// 一般来说，Swift 可以通过检测所赋的初值进行类型推断。 例如
let starks1 = ["Eddard", "Catelyn", "Robb", "Sansa"]

// 有多种方式访问数组中的元素，比如通过 Int 类型的下标，或者调用各种集合类型的方法

print(starks[0])
print(starks[1])
print(starks[2])
print(starks.first!)


// 哈希类型 / 字典
let ages = ["Robb" : 15, "sansa" : 12, "Arya" : 10, "Jon" : 15]


print(ages["Robb"]!)
print(ages["sansa"]!)
print(ages["Arya"]!)
// 要注意的是，我们解包这些值只是因为它们是可选值,它们有可能为 nil
// 使用可选绑定来解包字典中的值是较安全的，特别是你认为这些值很有可能为 nil 时

//可选绑定
if let aryaAge = ages["Aray"] {
    print(aryaAge)
}


// 我们也可以把数组存储在字典中，或者把字典存储在数组中，或者把他们混合使用
let families = [
    "Stark": ["Robb": 15, "Sansa": 12, "Arya": 10, "Jon": 15],
    "Baratheon": ["Joffrey": 13, "Tommen": 8]
]
let tommensAge = families["Baratheon"]!["Tommen"]!
print("Tommen is \(tommensAge) years old")

// 集合
// Swift3 中的集合和数组很相似，但集合的值是唯一的和无序的 初始化一个集合看起来就像初始化一个数组，唯一不同的是类型

//代码创建了一个字符串的集合。大于和小于符号 "<"">" 暗示 Swift 中的泛型类型，你可能注意到了 "Blue" 在列表中出现了两次，但是如果我们把颜色打印出来，马上就会发现：
let colors : Set<String> = ["Blue", "Red", "Orange", "Blue"]

print(colors)
// 你也许还注意到了顺序也不一致了，因为集合不会维持特定的顺序

// 我们无法像访问数组下标一样的方式去访问集合。但是可以用集合中内置的方法来增加或者删除元素，可以通过 contains 方法来查看是否集合中包含了该元素。

var colors1: Set<String> = ["Blue", "Red", "Orange", "Blue"]


colors1.insert("Black")
colors1.insert("Black")
colors1.remove("Red")
print(colors1)
print(colors1.contains("Black"))
print(colors1.contains("Red"))

//元组
// 元组并不是一种集合，而应该说是用一个标识符来表示多个不同变量。
let fullName = ("Jameson", "Quave")

//(String, String) 是一个元组类型，我们可以使用点语法来访问每一个元组的成员，看看下面的情况
print(fullName.0)
print(fullName.1)

// 元组也可以用一个新的多个变量名来构造
//由于我们没有用到 last name，可以忽略那个值通过使用下划线 _ ，并且仍然构造 first name
let (first, _) = ("Jameson", "Quave")

print(first)
//print(last)



// 控制流

// Swift 的控制流比起其他语言要优雅，我们先从 if 和 else 语句这些基本层面着手


if 10 > 5 {
    print("10 大于 5")
}else{
//    print("5 大于 10")
}

// 你也可以用括号来包裹 if 语句的条件
if (10 > 5) {
    print("10 大于 5")
}else{
//    print("5 大于 10")
}


// Swift 也支持 switch 语句，在编译期的时候检查你是否已经覆盖了所有的可能条件，如果你没有覆盖所有的条件，你得加上 defualt:case 来处理一些没有考虑到的情况

let name2 = "post"

switch name2 {
case "json":
    print("数据为json")
case "XML":
    print("数据为XML")
default:
    print("无法识别的数据")
}

// 循环和集合类型

// Swift3 不再支持你过去所使用的 C 风格的循环，取而代之的是使用枚举和 for-each 风格的循环，语法是 for element in array


let names = ["嘻嘻", "哈哈", "恩恩", "哼哼"]

for name3 in names {
    
    print("Name :\(name3)");
}

// 如果你想要循环整个数组，这个写法就很棒，没有 C 风格的数组，如果我们循环遍历一系列数字呢？Swift 中的 Range 和 Stride 给出了答案，如果想要打印到 10 里面3的倍数，可以使用 Range 通过使用语法 1…10 表示从 1 到 10 。然后我们打印每一个数字，那些数字都被 % 符号除以 3 ，并且检查它们的余数是不是都是0。


for i in 1...10 {
    if i % 3 == 0 {
        print(i)
    }
}

// 另外一种方式是通过 stride 每隔三个元素访问一次。stride 可以用很多方法来创建，但是最常见的是 stride(from: , to:, by:)，from value 就是跨步访问的起初值，然后 by 是每隔多少跨步值才能访问到 to 值。听起来有点绕，让我们来看实际的代码
let byThrees = stride(from: 3, to: 10, by: 3)

for n in byThrees{
    print(n)
}

// 集合都有一个 indices 属性用于循环中使用，它会返回一个集合的下标数组，非常适合访问或者过滤集合中某些元素的情况。这里回到我们的名称集合的例子，如果想要前三个名称，可以这样写




let names1 = ["Robb", "Sansa", "Arya", "Jon"]
for nameIndex in names1.indices {
    if nameIndex < 3 {
        print(names1[nameIndex])
    }
}

// 在集合中还有枚举的方法，它允许你通过遍历下标和值
let names2 = ["Robb", "Sansa", "Arya", "Jon"]

for (index, name4) in names2.enumerated(){
    print("\(index) : \(name4)")
}





















